package service;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.SimpleFSDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;

import common.Constants;

import crawler.CrawlerDocument;
import crawler.DocumentPool;

public class Indexer implements Runnable {
	
	private final Logger logger = Logger.getLogger(Indexer.class);
	
	private DocumentPool _pool = null;
	
	private IndexWriter _writer = null;
	
	private int _dumpThreshold = 
		Integer.parseInt(GlobalConfiguration.getInstance().get("dump_thres"));
	
	public Indexer(DocumentPool pool){
		_pool = pool;			
		
		Analyzer analyzer = new IKAnalyzer();		

		IndexWriterConfig config = new IndexWriterConfig(
				Constants.LUCENCE_VERSION, analyzer);	
		
		String indexPath = 
			GlobalConfiguration.getInstance().get(Constants.CONF_INDEX_PATH);
		
		Directory dir = null;
		try {
			dir = new SimpleFSDirectory(new File(indexPath), null);
		} catch (IOException e) {
			logger.error("{}", e);
		}

		try {
			_writer = new IndexWriter(dir, config);
		} catch (CorruptIndexException e) {
			logger.error("{}", e);
		} catch (LockObtainFailedException e) {
			logger.error("{}", e);
		} catch (IOException e) {
			logger.error("{}", e);
		}
	}

	@Override
	public void run() {

		int cnt = 0;
		
		while(true){
			try {
				CrawlerDocument doc = _pool.take();
				
				String title = (String)doc.getFeature(Constants.XPATH_TITLE);
				
				StringReader reader = new StringReader(title);
				
				Document indexDoc = new Document();
				
				Field indexFieldTitle = new Field(Constants.INDEX_FIELD_TITLE, reader);				
				indexDoc.add(indexFieldTitle);
				
				Field summaryFieldTitle = new Field(Constants.INDEX_FIELD_TITLE, title, 
						Field.Store.YES, Field.Index.NOT_ANALYZED);
				indexDoc.add(summaryFieldTitle);
				
				logger.debug("Index [" + title + "] into field[" + Constants.INDEX_FIELD_TITLE + "]");
				
				try {
					_writer.addDocument(indexDoc);
				} catch (CorruptIndexException e) {
					logger.error("{}", e);
				} catch (IOException e) {
					logger.error("{}", e);
				}				
				
				cnt++;
				
				if (cnt >= _dumpThreshold){
					try {
						_writer.commit();
						logger.info("" + cnt + " docs are indexed.");
					} catch (CorruptIndexException e) {
						logger.error("{}", e);
					} catch (IOException e) {
						logger.error("{}", e);
					}
					cnt = 0;
				}
				
				
			} catch (InterruptedException e) {
				logger.error("{}", e);
			}
		}
		
	}
	
	public void stop(){
		try {
			_writer.close();
		} catch (CorruptIndexException e) {
			logger.error("{}", e);
		} catch (IOException e) {
			logger.error("{}", e);
		}
	}

}
